﻿using System;
using System.IO;

namespace SocialKit.LightRest
{
    /// <summary>
    /// Represents a file form.
    /// </summary>
    public sealed class HttpFormFile : IDisposable
    {
        /// <summary>
        /// Represents the "application/octet-stream" string.
        /// </summary>
        public static readonly string OctetStreamFileContentType = "application/octet-stream";


        /// <summary>
        /// Gets or sets the name of this form.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the file name of this form.
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// Gets or sets the file content type.
        /// </summary>
        public string FileContentType { get; set; }

        /// <summary>
        /// Gets or sets the file content.
        /// </summary>
        public byte[] FileContent { get; set; }


        /// <summary>
        /// Initialize a new instance of SocialKit.LightRest.HttpFormFile class.
        /// </summary>
        public HttpFormFile() { }

        /// <summary>
        /// Initialize a new instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name and file name.
        /// </summary>
        /// <param name="name">The form name.</param>
        /// <param name="file">The file name.</param>
        public HttpFormFile(string name, string file)
            : this(name, file, GetMimeContentType(file))
        {
            if (!File.Exists(file))
                throw new FileNotFoundException("The file \"" + file + "\" is not there.");
        }

        /// <summary>
        /// Initialize a new instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name, file name and file type.
        /// </summary>
        /// <param name="name">The form name.</param>
        /// <param name="file">The file name.</param>
        /// <param name="fileContentType">The file Content-Type.</param>
        public HttpFormFile(string name, string file, string fileContentType)
            : this(name, file, fileContentType, ReadFileContent(file))
        {
            if (!File.Exists(file))
                throw new FileNotFoundException("The file \"" + file + "\" is not there.");
        }

        /// <summary>
        /// Create an instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name, file name, file type and the file content stream.
        /// </summary>
        /// <param name="name">The name of the new form.</param>
        /// <param name="file">The file path of the new form.</param>
        /// <param name="fileContent">The content stream of file.</param>
        public HttpFormFile(string name, string file, Stream fileContent)
            : this(name, file, GetMimeContentType(file), fileContent.ReadAllBytes())
        {
        }

        /// <summary>
        /// Create an instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name, file name, file type and the file content stream.
        /// </summary>
        /// <param name="name">The name of the new form.</param>
        /// <param name="file">The file path of the new form.</param>
        /// <param name="fileContent">The content of file.</param>
        public HttpFormFile(string name, string file, byte[] fileContent)
            : this(name, file, GetMimeContentType(file), fileContent)
        {
        }

        /// <summary>
        /// Create an instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name, file name, file type and the file content stream.
        /// </summary>
        /// <param name="name">The name of the new form.</param>
        /// <param name="file">The file path of the new form.</param>
        /// <param name="fileContentType">The file content type string.</param>
        /// <param name="fileContent">The content stream of file.</param>
        public HttpFormFile(string name, string file, string fileContentType, Stream fileContent)
            : this(name, file, fileContentType, fileContent.ReadAllBytes())
        {
        }

        /// <summary>
        /// Create an instance of SocialKit.LightRest.HttpFormFile class with specified
        /// form name, file name, file type and the file content.
        /// </summary>
        /// <param name="name">The name of the new form.</param>
        /// <param name="file">The file path of the new form.</param>
        /// <param name="fileContentType">The file content type string.</param>
        /// <param name="fileContent">The content of file.</param>
        public HttpFormFile(string name, string file, string fileContentType, byte[] fileContent)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            if (string.IsNullOrEmpty(file))
                throw new ArgumentNullException("file");

            if (string.IsNullOrEmpty(fileContentType))
                fileContentType = OctetStreamFileContentType;

            this.Name = name;
            this.FileName = Path.GetFileName(file);
            this.FileContentType = fileContentType;
            this.FileContent = fileContent;
        }


        /// <summary>
        /// Returns the normalized description string.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0}={1}", this.Name, this.FileName);
        }

        #region IDisposable Members

        /// <summary>
        /// Disposes the file content.
        /// </summary>
        public void Dispose()
        {
            if (this.FileContent != null)
                this.FileContent = null;
        }

        #endregion

        static byte[] ReadFileContent(string file)
        {
            if (File.Exists(file))
            {
                using (var fs = File.OpenRead(file))
                {
                    return fs.ReadAllBytes();
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the MIME Type name of specified file name.
        /// </summary>
        /// <param name="file">The file path.</param>
        /// <returns></returns>
        public static string GetMimeContentType(string file)
        {
            if (string.IsNullOrEmpty(file))
                throw new ArgumentNullException("file");

            var ext = Path.GetExtension(file).ToLower();

            var regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);

            if (regKey != null && regKey.GetValue("Content Type") != null)
            {
                return regKey.GetValue("Content Type").ToString();
            }

            return OctetStreamFileContentType;
        }
    }
}